/*
 * ========================================================================
 *
 *       Filename:  deck.cpp
 *
 *    Description:  This is the implementation of the deck.
 *
 *        Version:  1.0
 *        Created:  05/10/2010 08:35:53 PM
 *       Revision:  none
 *       Compiler:  g++
 *
 *         Author:  Alex Avance (aa), aravance@gmail.com
 *        Company:  independent
 *
 * ========================================================================
 *
 * Copyright (C) 2010 Alex Avance
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-
 * 1307, USA.
 *
 * ========================================================================
 */
#include "deck.h"
#include <cstdlib>

/**************************************************************************
Class Name: StudyDeck
Method Name: StudyDeck
Description: constructor
**************************************************************************/
StudyDeck::StudyDeck ()
  : StatInfo(), m_Container()
{} // ----- end of method StudyDeck::StudyDeck (constructor) -----

/**************************************************************************
Class Name: StudyDeck
Method Name: StudyDeck
Description: copy constructor
**************************************************************************/
StudyDeck::StudyDeck ( const StudyDeck &other )
  : StatInfo( other ), m_Container( other.m_Container )
{} // ----- end of method StudyDeck::StudyDeck (copy constructor) -----

/**************************************************************************
Class Name: StudyDeck
Method Name: StudyDeck
Description: constructor
**************************************************************************/
StudyDeck::StudyDeck ( const DeckT &deck )
  : StatInfo(), m_Container( deck )
{ RecountStats(); } // ----- end of method StudyDeck::StudyDeck (constructor) -----

/**************************************************************************
Class Name: StudyDeck
Method Name: StudyDeck
Description: destructor
**************************************************************************/
StudyDeck::~StudyDeck ()
{} // ----- end of method StudyDeck::~StudyDeck (destructor) -----
/**************************************************************************
Class: StudyDeck
Method: Iterator accessors
Description: Return appropriate iterators.
**************************************************************************/
StudyDeck::iterator StudyDeck::Begin ()
{ return m_Container.begin(); } // ----- end of method StudyDeck::Begin -----
StudyDeck::iterator StudyDeck::begin ()
{ return m_Container.begin(); } // ----- end of method StudyDeck::begin -----

StudyDeck::const_iterator StudyDeck::Begin () const
{ return m_Container.begin(); } // ----- end of method StudyDeck::Begin -----
StudyDeck::const_iterator StudyDeck::begin () const
{ return m_Container.begin(); } // ----- end of method StudyDeck::begin -----

StudyDeck::iterator StudyDeck::End ()
{ return m_Container.end(); } // ----- end of method StudyDeck::End -----
StudyDeck::iterator StudyDeck::end ()
{ return m_Container.end(); } // ----- end of method StudyDeck::end -----

StudyDeck::const_iterator StudyDeck::End () const
{ return m_Container.end(); } // ----- end of method StudyDeck::End -----
StudyDeck::const_iterator StudyDeck::end () const
{ return m_Container.end(); } // ----- end of method StudyDeck::end -----

StudyDeck::reverse_iterator StudyDeck::RBegin ()
{ return m_Container.rbegin(); } // ----- end of method StudyDeck::RBegin -----
StudyDeck::reverse_iterator StudyDeck::rbegin ()
{ return m_Container.rbegin(); } // ----- end of method StudyDeck::rbegin -----

StudyDeck::const_reverse_iterator StudyDeck::RBegin () const
{ return m_Container.rbegin(); } // ----- end of method StudyDeck::RBegin -----
StudyDeck::const_reverse_iterator StudyDeck::rbegin () const
{ return m_Container.rbegin(); } // ----- end of method StudyDeck::rbegin -----

StudyDeck::reverse_iterator StudyDeck::REnd ()
{ return m_Container.rend(); } // ----- end of method StudyDeck::REnd -----
StudyDeck::reverse_iterator StudyDeck::rend ()
{ return m_Container.rend(); } // ----- end of method StudyDeck::rend -----

StudyDeck::const_reverse_iterator StudyDeck::REnd () const
{ return m_Container.rend(); } // ----- end of method StudyDeck::REnd -----
StudyDeck::const_reverse_iterator StudyDeck::rend () const
{ return m_Container.rend(); } // ----- end of method StudyDeck::rend -----

/**************************************************************************
Class: StudyDeck
Method: At
Description: Access an element at a position.
**************************************************************************/
StudyDeck::CardT& StudyDeck::At ( size_t pos )
{ return m_Container.at( pos ); } // ----- end of method StudyDeck::At -----
StudyDeck::CardT& StudyDeck::at ( size_t pos )
{ return At( pos ); } // ----- end of method StudyDeck::at -----

const StudyDeck::CardT& StudyDeck::At ( size_t pos ) const
{ return m_Container.at( pos ); } // ----- end of method StudyDeck::At -----
const StudyDeck::CardT& StudyDeck::at ( size_t pos ) const
{ return At( pos ); } // ----- end of method StudyDeck::at -----

/**************************************************************************
Class: StudyDeck
Method: Top
Description: Access the top element.
**************************************************************************/
StudyDeck::CardT& StudyDeck::Top ()
{ return m_Container.front(); } // ----- end of method StudyDeck::Top -----
StudyDeck::CardT& StudyDeck::top ()
{ return Top(); } // ----- end of method StudyDeck::top -----

const StudyDeck::CardT& StudyDeck::Top () const
{ return m_Container.front(); } // ----- end of method StudyDeck::Top -----
const StudyDeck::CardT& StudyDeck::top () const
{ return Top(); } // ----- end of method StudyDeck::top -----

/**************************************************************************
Class: StudyDeck
Method: Bottom
Description: Access the top element.
**************************************************************************/
StudyDeck::CardT& StudyDeck::Bottom ()
{ return m_Container.back(); } // ----- end of method StudyDeck::Bottom -----
StudyDeck::CardT& StudyDeck::bottom ()
{ return Bottom(); } // ----- end of method StudyDeck::bottom -----

const StudyDeck::CardT& StudyDeck::Bottom () const
{ return m_Container.back(); } // ----- end of method StudyDeck::Bottom -----
const StudyDeck::CardT& StudyDeck::bottom () const
{ return Bottom(); } // ----- end of method StudyDeck::bottom -----

/**************************************************************************
Class: StudyDeck
Method: Size, Count
Description: Return the number of elements.
**************************************************************************/
size_t StudyDeck::Size () const
{ return m_Container.size(); } // ----- end of method StudyDeck::Size -----
size_t StudyDeck::size () const
{ return Size(); } // ----- end of method StudyDeck::size -----

size_t StudyDeck::Count () const
{ return m_Container.size(); } // ----- end of method StudyDeck::Count -----
size_t StudyDeck::count () const
{ return Count(); } // ----- end of method StudyDeck::count -----

/**************************************************************************
Class: StudyDeck
Method: Empty
Description: Return true if there are no elements.
**************************************************************************/
bool StudyDeck::Empty () const
{ return m_Container.empty(); } // ----- end of method StudyDeck::Empty -----
bool StudyDeck::empty () const
{ return Empty(); } // ----- end of method StudyDeck::empty -----

/**************************************************************************
Class: StudyDeck
Method: Pop
Description: Remove the top element.
**************************************************************************/
void StudyDeck::Pop ()
{
  m_Right-= Top().Right();
  m_Wrong-= Top().Wrong();
  m_Container.pop_front();
} // ----- end of method StudyDeck::Pop -----
void StudyDeck::pop ()
{ Pop(); } // ----- end of method StudyDeck::pop -----

/**************************************************************************
Class: StudyDeck
Method: Push
Description: Push a card onto the top of the deck.
**************************************************************************/
void StudyDeck::Push ( const CardT &card )
{
  m_Container.push_front( card );
  m_Right+= card.Right();
  m_Wrong+= card.Wrong();
} // ----- end of method StudyDeck::Push -----
void StudyDeck::push ( const CardT &card )
{ Push( card ); } // ----- end of method StudyDeck::push -----

void StudyDeck::Push ( const InfoT &front, const InfoT &back,
                       StatT right, StatT wrong )
{
  Push( CardT( front, back, right, wrong ) );
} // ----- end of method StudyDeck::Push -----
void StudyDeck::push ( const InfoT &front, const InfoT &back,
                       StatT right, StatT wrong )
{ Push( front, back, right, wrong ); } // ----- end of method StudyDeck::push -----

/**************************************************************************
Class: StudyDeck
Method: Next
Description: Cycle the deck forward one card.
**************************************************************************/
void StudyDeck::Next ()
{
  m_Container.push_back( m_Container.front() );
  m_Container.pop_front();
} // ----- end of method StudyDeck::Next -----
void StudyDeck::next ()
{ Next(); } // ----- end of method StudyDeck::next -----

/**************************************************************************
Class: StudyDeck
Method: Prev
Description: Cycle the deck backward one card.
**************************************************************************/
void StudyDeck::Prev ()
{
  m_Container.push_front( m_Container.back() );
  m_Container.pop_back();
} // ----- end of method StudyDeck::Prev -----
void StudyDeck::prev ()
{ Prev(); } // ----- end of method StudyDeck::prev -----

/**************************************************************************
Class: StudyDeck
Method: Clear
Description: Empty out the deck.
**************************************************************************/
void StudyDeck::Clear ()
{
  StatInfo::ResetStats();
  m_Container.clear();
} // ----- end of method StudyDeck::Clear -----
void StudyDeck::clear ()
{ Clear(); } // ----- end of method StudyDeck::clear -----

/**************************************************************************
Class: StudyDeck
Method: Assign
Description: Assign the contents of the deck.
**************************************************************************/
const StudyDeck& StudyDeck::Assign ( const StudyDeck &other )
{ return *this= other; } // ----- end of method StudyDeck::Assign -----
const StudyDeck& StudyDeck::assign ( const StudyDeck &other )
{ return *this= other; } // ----- end of method StudyDeck::assign -----

const StudyDeck& StudyDeck::Assign ( const DeckT &deck )
{ return *this= deck; } // ----- end of method StudyDeck::Assign -----
const StudyDeck& StudyDeck::assign ( const DeckT &deck )
{ return *this= deck; } // ----- end of method StudyDeck::assign -----

/**************************************************************************
Class: StudyDeck
Method: Append
Description: Add content to the end of the deck.
**************************************************************************/
const StudyDeck& StudyDeck::Append ( const StudyDeck &other )
{
  return Append( other.m_Container );
} // ----- end of method StudyDeck::Append -----
const StudyDeck& StudyDeck::append ( const StudyDeck &other )
{ return Append( other ); } // ----- end of method StudyDeck::append -----

const StudyDeck& StudyDeck::Append ( const DeckT &deck )
{
  m_Container.insert( end(), deck.begin(), deck.end() );
  RecountStats();
  return *this;
} // ----- end of method StudyDeck::Append -----
const StudyDeck& StudyDeck::append ( const DeckT &deck )
{ return Append( deck ); } // ----- end of method StudyDeck::append -----

const StudyDeck& StudyDeck::Append ( const CardT &card )
{
  m_Container.push_back( card );
  m_Right+= card.Right();
  m_Wrong+= card.Wrong();
  return *this;
} // ----- end of method StudyDeck::Append -----
const StudyDeck& StudyDeck::append ( const CardT &card )
{ return Append( card ); } // ----- end of method StudyDeck::append -----

const StudyDeck& StudyDeck::Append ( const InfoT &front, const InfoT &back,
                                     StatT right, StatT wrong )
{
  return Append( CardT( front, back, right, wrong ) );
} // ----- end of method StudyDeck::Append -----
const StudyDeck& StudyDeck::append ( const InfoT &front, const InfoT &back,
                                     StatT right, StatT wrong )
{ return Append( front, back, right, wrong ); } // ----- end of method StudyDeck::append -----

/**************************************************************************
Class: StudyDeck
Method: Insert
Description: Insert elements at a given position.
**************************************************************************/
void StudyDeck::Insert ( iterator pos, const StudyDeck &other )
{
  Insert( pos, other.begin(), other.end() );
  m_Right+= other.Right();
  m_Wrong+= other.Wrong();
} // ----- end of method StudyDeck::Insert -----
void StudyDeck::Insert ( size_t pos, const StudyDeck &other )
{ Insert( m_Container.begin() + pos, other ); } // ----- end of method StudyDeck::Insert -----
void StudyDeck::insert ( iterator pos, const StudyDeck &other )
{ Insert( pos, other ); } // ----- end of method StudyDeck::insert -----
void StudyDeck::insert ( size_t pos, const StudyDeck &other )
{ Insert( m_Container.begin() + pos, other ); } // ----- end of method StudyDeck::insert -----

void StudyDeck::Insert ( iterator pos, const DeckT &deck )
{
  m_Container.insert( pos, deck.begin(), deck.end() );
  RecountStats();
} // ----- end of method StudyDeck::Insert -----
void StudyDeck::Insert ( size_t pos, const DeckT &deck )
{ Insert( m_Container.begin() + pos, deck ); } // ----- end of method StudyDeck::Insert -----
void StudyDeck::insert ( iterator pos, const DeckT &deck )
{ Insert( pos, deck ); } // ----- end of method StudyDeck::insert -----
void StudyDeck::insert ( size_t pos, const DeckT &deck )
{ Insert( m_Container.begin() + pos, deck ); } // ----- end of method StudyDeck::insert -----

void StudyDeck::Insert ( iterator pos, const CardT &card )
{
  m_Container.insert( pos, card );
  m_Right+= card.Right();
  m_Wrong+= card.Wrong();
} // ----- end of method StudyDeck::Insert -----
void StudyDeck::Insert ( size_t pos, const CardT &card )
{ Insert( m_Container.begin() + pos, card ); } // ----- end of method StudyDeck::Insert -----
void StudyDeck::insert ( iterator pos, const CardT &card )
{ Insert( pos, card ); } // ----- end of method StudyDeck::insert -----
void StudyDeck::insert ( size_t pos, const CardT &card )
{ Insert( m_Container.begin() + pos, card ); } // ----- end of method StudyDeck::insert -----

/**************************************************************************
Class: StudyDeck
Method: Erase
Description: Remove elements from the deck.
**************************************************************************/
void StudyDeck::Erase ( iterator start, iterator stop )
{
  m_Container.erase( start, stop );
  RecountStats();
} // ----- end of method StudyDeck::Erase -----
void StudyDeck::erase ( iterator start, iterator stop )
{ Erase( start, stop ); } // ----- end of method StudyDeck::erase -----

void StudyDeck::Erase ( iterator pos )
{
  m_Container.erase( pos );
  RecountStats();
} // ----- end of method StudyDeck::Erase -----
void StudyDeck::erase ( iterator pos )
{ Erase( pos ); } // ----- end of method StudyDeck::erase -----

void StudyDeck::Erase ( size_t pos )
{ Erase( begin() + pos ); } // ----- end of method StudyDeck::Erase -----
void StudyDeck::erase ( size_t pos )
{ Erase( pos ); } // ----- end of method StudyDeck::erase -----

/**************************************************************************
Class: StudyDeck
Method: Sort
Description: Sort the deck calling the protected member function.
**************************************************************************/
void StudyDeck::Sort ()
{
  m_Sort( begin(), ( end() - 1 ) );
} // ----- end of method StudyDeck::Sort -----
void StudyDeck::sort ()
{ Sort(); } // ----- end of method StudyDeck::sort -----

/**************************************************************************
Class: StudyDeck
Method: Shuffle
Description: Shuffle the deck.
**************************************************************************/
void StudyDeck::Shuffle ()
{
  iterator loc= begin();
  size_t count= size();

  for ( size_t i= 0; i < count; ++i, ++loc )
  {
    size_t r= rand() % ( count - i );

    CardT temp= loc[0];
    loc[0]= loc[r];
    loc[r]= temp;
  }
} // ----- end of method StudyDeck::Shuffle -----
void StudyDeck::shuffle ()
{ Shuffle(); } // ----- end of method StudyDeck::shuffle -----

/**************************************************************************
Class: StudyDeck
Method: Guess
Description: Define this functions implementation of the Guess for stat
             information.
**************************************************************************/
void StudyDeck::Guess ( bool result )
{
  Top().Guess( result );
  StatInfo::Guess( result );
} // ----- end of method StudyDeck::Guess -----
void StudyDeck::guess ( bool result )
{ Guess( result ); } // ----- end of method StudyDeck::Guess -----

/**************************************************************************
Class: StudyDeck
Method: ResetStats
Description: Reset stats for deck and each individual card.
**************************************************************************/
void StudyDeck::ResetStats ()
{
  for ( iterator it= begin(); it != end(); ++it )
    it->ResetStats();
  StatInfo::ResetStats();
} // ----- end of method StudyDeck::ResetStats -----
void StudyDeck::resetstats ()
{ ResetStats(); } // ----- end of method StudyDeck::resetstats -----

/**************************************************************************
Class: StudyDeck
Method: RecountStats
Description: Recount the stat information for the deck.
**************************************************************************/
void StudyDeck::RecountStats ()
{
  StatInfo::ResetStats();
  for ( iterator it= begin(); it != end(); ++it )
  {
    m_Right+= it->Right();
    m_Wrong+= it->Wrong();
  }
} // ----- end of method StudyDeck::RecountStats -----
void StudyDeck::recountstats ()
{ RecountStats(); } // ----- end of method StudyDeck::recountstats -----

/**************************************************************************
Class Name: StudyDeck
Method Name: operator=
Description: assignment operator
**************************************************************************/
StudyDeck& StudyDeck::operator= ( const DeckT &deck )
{
  m_Container= deck;
  RecountStats();

  return *this;
} // ----- end of method StudyDeck::operator= (assignment operator) -----

/**************************************************************************
Class Name: StudyDeck
Method Name: operator=
Description: assignment operator
**************************************************************************/
StudyDeck& StudyDeck::operator= ( const StudyDeck &other )
{
  if ( this != &other )
  {
    m_Container= other.m_Container;
    m_Right= other.m_Right;
    m_Wrong= other.m_Wrong;
  }
  return *this;
} // ----- end of method StudyDeck::operator= (assignment operator) -----

/**************************************************************************
Class Name: StudyDeck
Method Name: operator[]
Description: access operator
**************************************************************************/
StudyDeck::CardT& StudyDeck::operator[] ( size_t pos )
{ return m_Container[pos]; }

const StudyDeck::CardT& StudyDeck::operator[] ( size_t pos ) const
{ return m_Container[pos]; }

/**************************************************************************
Class: StudyDeck
Method: m_Sort
Description: This is the work horse for the sort function.
**************************************************************************/
void StudyDeck::m_Sort ( iterator left, iterator right )
{
  if ( left >= right )
    return;

  iterator index_loc,
           high= right,
           low= left;

  CardT index;

  index_loc= left;
  index= *index_loc;

  *index_loc= *right;

  while ( low != high )
  {
    while ( *low < index && low != high )
      ++low;

    *high= *low;
    if ( high != low )
      --high;

    while ( *high >= index && high != low )
      --high;

    *low= *high;
    if ( low != high )
      ++low;
  }

  index_loc= low;
  *index_loc= index;

  m_Sort( left, index_loc - 1 );
  m_Sort( index_loc + 1, right );
} // ----- end of method StudyDeck::m_Sort -----

